package com.gamejelly.proxy.server;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.Epoll;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by haoyifen on 2017/6/19 19:08.
 */
public class ServiceStarter {


    int port;

    public ServiceStarter(int port) {
        this.port = port;
    }

    private static final Logger logger = LoggerFactory.getLogger(ServiceStarter.class);
    @Setter
    private ServerChannelInitializer serverChannelInitializer;
    private final boolean epollEnable = Epoll.isAvailable();
    private final EventLoopGroup bossGroup = epollEnable ? new EpollEventLoopGroup(1) : new NioEventLoopGroup(1);
    @Setter
    private EventLoopGroup workerGroup;

    public ChannelFuture start() {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        try {
            if (workerGroup == null) {
                int threadNums = Runtime.getRuntime().availableProcessors();
                workerGroup = epollEnable ? new EpollEventLoopGroup(threadNums) : new NioEventLoopGroup(threadNums);
            }
            serverBootstrap
                    .group(bossGroup, workerGroup)
                    .channel(epollEnable ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(serverChannelInitializer);
            ChannelFuture future = serverBootstrap.bind(port).sync();
            if (future.isSuccess()) {
                logger.info("proxy server start at port:{} success", port);
            }
            return future;
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
